package com.tiny.tinyweb.core.aop;

import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.springframework.aop.interceptor.AbstractTraceInterceptor;

import com.tiny.tinyweb.core.ldap.access.EntryMapper;
import com.tiny.tinyweb.core.log.LogInfo;
import com.tiny.tinyweb.core.utils.ReflectionUtils;

/**
 * 基于 {@link org.springframework.aop.interceptor.AbstractTraceInterceptor}
 * 实现的LDAP操作执行状态的跟踪器类，用来将目标方法的参数信息输出到调试日志。
 *
 * @see {@link org.springframework.aop.interceptor.AbstractTraceInterceptor}
 * @author wxiaobin
 * @version 1.0
 * @since 1.0
 */
public class LdapLogInterceptor extends AbstractTraceInterceptor {

    private static final long serialVersionUID = 1L;

    /**
     * 跟踪目标方法的执行，将 {@link org.springframework.ldap.core.LdapTemplate}
     * 中目标方法的执行参数输出到调试日志。
     *
     * @param invocation 由{@link org.aopalliance.intercept.MethodInvocation}包装的方法调用对象
     * @param logger 日志输出对象，通过loggerName来使用指定的类名创建
     * @return 目标方法的返回值
     */
    @Override
    protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
        // 跳过“toString”、“toJSON”和“hashCode”方法
        String method = invocation.getMethod().getName();
        if ("toString".equals(method) || "toJSON".equals(method) || "hashCode".equals(method)) {
            return invocation.proceed();
        }

        // 创建一个保存日志信息的对象
        LogInfo logInfo = new LogInfo();
        // 获得目标方法名称
        logInfo.setOperation(method);

        try {
            // 所有参数信息输出到调试日志
            for (Object arg : invocation.getArguments()) {
                if (arg == null) {
                    logInfo.setMessage("<null>");
                    logger.debug(logInfo.toString());
                    continue;
                }
                String name = arg.getClass().getSimpleName();
                String value = "";
                if (arg instanceof EntryMapper<?>) {
                    // 映射器的包装类名
                    value = String.valueOf(ReflectionUtils.getPropertyValue(arg, "mappedClass"));
                } else {
                    // 参数值
                    value = arg.toString();
                }
                logInfo.setMessage("%1$s=[%2$s]", name, value);
                logger.debug(logInfo.toString());
            }
        } catch (Exception e) {
            // 从Spring的LdapTemplate中获取参数信息失败时，输出警告日志
            logInfo.setMessage("Can not get parameter info from this method. [%1$s]",
                    e.getMessage());
            logger.warn(logInfo.toString());
        }

        // 调用目标方法，返回目标方法的返回值
        return invocation.proceed();
    }

    @Override
    protected boolean isLogEnabled(Log logger) {
        return logger.isErrorEnabled();
    }
}
